
/* 任务：基于 errgroup 实现一个 http server 的启动和关闭 ，以及 linux signal 信号的注册和处理，要保证能够一个退出，全部注销退出。*/
package main

import (
	"context"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"golang.org/x/sync/errgroup"
)

func serverApp(server *http.Server)  error {
	http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
		fmt.Fprintln(writer,"hello ,"+request.Host)
	})
	return  server.ListenAndServe()
}


func main() {
	ctx, cancel := context.WithCancel(context.Background())
	// 使用 errgroup 进行 goroutine 取消
	g, errCtx := errgroup.WithContext(ctx)
	// 创建一个http server
	srv := &http.Server{Addr: ":8080"}

	g.Go(func() error {
		return serverApp(srv)
	})

	g.Go(func() error {
		<- errCtx.Done()
		fmt.Println("http server stop")
		return srv.Shutdown(errCtx)
	})

	chanel := make(chan os.Signal, 1) // buffer 为1的 chan
	signal.Notify(chanel)

	g.Go(func() error {
		for {
			select {
			case <-errCtx.Done(): // 因为 cancel、timeout、deadline 都可能导致 Done 被 close
				return errCtx.Err()
			case <-chanel: // 因为 kiil signal而终止
				cancel()
			}
		}
		return nil
	})

	if err := g.Wait(); err != nil {
		fmt.Println("group error: ", err)
	}
	fmt.Println("all group done!")

}
